#include <iostream>
#include <cstdio>
#include<unistd.h>
#include<vector>
#include<string>
#include <pthread.h>
using namespace std;

int cnt = 1;
pthread_mutex_t mutex;
pthread_cond_t cond;
void* Routine(void* arg)
{
	const char* str = (const char *)arg;
	cout << str << " run ..." << endl;
	while(true){
		pthread_mutex_lock(&mutex);

		pthread_cond_wait(&cond, &mutex);//pthread_cond_wait让线程等待的时候，会自动释放锁！
		//若不满足条件则会阻塞，持有的互斥锁也会被释放，
		//等到该线程被唤醒时，会再次持有锁访问临界区
		cout << str << " say hello !!! cnt = " << cnt++ << endl;

		pthread_mutex_unlock(&mutex);
	}
}
int main()
{
	vector<pthread_t> tids(3);
	vector<string> threads{"thread1", "thread2", "thread3"};
	pthread_mutex_init(&mutex, nullptr);
	pthread_cond_init(&cond, nullptr);
	
	for(int i=0; i<3; i++)
	{
		pthread_create(&tids[i], nullptr, Routine, (void*)threads[i].c_str());
		usleep(10);
	}
	
	while (true){
		pthread_cond_signal(&cond);
		//pthread_cond_broadcast(&cond);
		sleep(1);
	}
	
	for(int i=0; i<3; i++)
	{
		pthread_join(tids[i], nullptr);
	}

	pthread_cond_destroy(&cond);
	pthread_mutex_destroy(&mutex);

	return 0;
}


// #include <stdio.h>
// #include <pthread.h>

// pthread_mutex_t mutex;
// void* Routine(void* arg)
// {
// 	pthread_mutex_lock(&mutex);
// 	pthread_mutex_lock(&mutex);
	
// 	pthread_exit((void*)0);
// }
// int main()
// {
// 	pthread_t tid;
// 	pthread_mutex_init(&mutex, NULL);
// 	pthread_create(&tid, NULL, Routine, NULL);
	
// 	pthread_join(tid, NULL);
// 	pthread_mutex_destroy(&mutex);
// 	return 0;
// }


// #include <stdio.h>
// #include <unistd.h>
// #include <pthread.h>

// int tickets = 1000;
// pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
// void* TicketGrabbing(void* arg)
// {
// 	const char* name = (char*)arg;
// 	while (true){
// 		pthread_mutex_lock(&mutex);
// 		if (tickets > 0){
// 			usleep(10000);
// 			printf("[%s] get a ticket, left tickets: %d\n", name, --tickets);
// 			pthread_mutex_unlock(&mutex);

// 			usleep(16);//模拟抢票后的反应时间
// 			//否则该线程抢完票后还会立即申请锁进行抢票，导致其他线程无法抢票
// 		}
// 		else{
// 			pthread_mutex_unlock(&mutex);
// 			break;
// 		}
// 	}
// 	printf("%s quit!\n", name);
// 	pthread_exit((void*)0);
// }
// int main()
// {
// 	pthread_t t1, t2, t3, t4;
// 	pthread_create(&t1, NULL, TicketGrabbing, (void*)"thread 1");
// 	pthread_create(&t2, NULL, TicketGrabbing, (void*)"thread 2");
// 	pthread_create(&t3, NULL, TicketGrabbing, (void*)"thread 3");
// 	pthread_create(&t4, NULL, TicketGrabbing, (void*)"thread 4");
	
// 	pthread_join(t1, NULL);
// 	pthread_join(t2, NULL);
// 	pthread_join(t3, NULL);
// 	pthread_join(t4, NULL);
// 	return 0;
// }
